﻿using System;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Threading;
using NSubstitute;
using Phoenix.Diagnostics;
using Phoenix.Exceptions;
using Phoenix.Frames;
using Phoenix.Framework;
using Xunit;

namespace Phoenix.Tests
{
    public class PhoenixHostBuilderFacts
    {
        readonly PhoenixHostBuilder builder;
        readonly IControllerLocator controllerLocator;
        readonly IControllerFactory controllerFactory;
        readonly IViewLocator viewLocator;
        readonly IErrorReporter errorReporter;
        readonly IActionInvoker actionInvoker;

        public PhoenixHostBuilderFacts()
        {
            controllerLocator = Substitute.For<IControllerLocator>();
            controllerFactory = Substitute.For<IControllerFactory>();
            viewLocator = Substitute.For<IViewLocator>();
            errorReporter = Substitute.For<IErrorReporter>();
            actionInvoker = Substitute.For<IActionInvoker>();
            actionInvoker.InvokeAction(null).ReturnsForAnyArgs(Task.Factory.StartNew(()=>{}));

            builder = new PhoenixHostBuilder(TaskScheduler.Default, Dispatcher.CurrentDispatcher);
            builder.UseControllerLocator(controllerLocator);
            builder.UseControllerFactory(controllerFactory);
            builder.UseViewLocator(viewLocator);
            builder.UseErrorReporter(errorReporter);
        }

        [Fact]
        public void host_builder_calls_show_on_host_target()
        {
            // arrange
            var target = Substitute.For<IPhoenixHostTarget>();

            // act
            builder.Run(target).Wait(1000);

            // assert
            target.Received().Show(Arg.Any<INavigationFrame>());
        }

        [Fact]
        public void host_builder_registers_assembly_with_controller_locator()
        {
            // arrange
            var target = new TestHostTarget();

            // act
            builder.Run(target).Wait(1000);

            // assert
            controllerLocator.Received().AddAssemblyToScan(typeof(AutofacPhoenixHostBuilderFacts).Assembly);
        }

        [Fact]
        public void throws_when_default_controller_action_not_specified()
        {
            // arrange
            builder.Configuration.DefaultControllerAction = null;
            var target = new TestHostTarget();

            // act
            try
            {
                builder.Run(target).Wait(1000);
            }
            catch (AggregateException ex)
            {
                // assert
                Assert.IsType<ControllerActionInvocationFailedException>(ex.InnerException);
                Assert.Equal("No Default Controller Action Specified", ex.InnerException.Message);
            }
        }

        public class TestHostTarget : IPhoenixHostTarget
        {
            public void Show(INavigationFrame navigationFrame)
            {
                NavigationFrame = navigationFrame;
            }

            public INavigationFrame NavigationFrame { get; private set; }

            public Control ContentHost
            {
                get { return null; }
            }
        }
    }
}